package com.governtalk.backend.service.impl;

import com.governtalk.backend.dto.wrongquestion.WrongQuestionDto;
import com.governtalk.backend.entity.Question;
import com.governtalk.backend.entity.QuestionCategory;
import com.governtalk.backend.entity.WrongQuestion;
import com.governtalk.backend.repository.QuestionCategoryRepository;
import com.governtalk.backend.repository.QuestionRepository;
import com.governtalk.backend.repository.WrongQuestionRepository;
import com.governtalk.backend.service.WrongQuestionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class WrongQuestionServiceImpl implements WrongQuestionService {
    
    @Autowired
    private WrongQuestionRepository wrongQuestionRepository;
    
    @Autowired
    private QuestionRepository questionRepository;
    
    @Autowired
    private QuestionCategoryRepository categoryRepository;
    
    @Override
    public WrongQuestionDto addWrongQuestion(WrongQuestionDto wrongQuestionDto) {
        // 检查是否已存在
        Optional<WrongQuestion> existing = wrongQuestionRepository.findByUserIdAndQuestionId(
            wrongQuestionDto.getUserId(), wrongQuestionDto.getQuestionId());
        
        if (existing.isPresent()) {
            // 如果已存在，更新错误时间
            WrongQuestion existingWrong = existing.get();
            existingWrong.setErrorTime(LocalDateTime.now());
            existingWrong.setUserAnswer(wrongQuestionDto.getUserAnswer());
            existingWrong.setCorrectAnswer(wrongQuestionDto.getCorrectAnswer());
            existingWrong.setErrorReason(wrongQuestionDto.getErrorReason());
            wrongQuestionRepository.save(existingWrong);
            return convertToDto(existingWrong);
        }
        
        // 创建新的错题记录
        WrongQuestion wrongQuestion = WrongQuestion.builder()
            .userId(wrongQuestionDto.getUserId())
            .questionId(wrongQuestionDto.getQuestionId())
            .userAnswer(wrongQuestionDto.getUserAnswer())
            .correctAnswer(wrongQuestionDto.getCorrectAnswer())
            .errorReason(wrongQuestionDto.getErrorReason())
            .reviewNotes(wrongQuestionDto.getReviewNotes())
            .isReviewed(wrongQuestionDto.getIsReviewed() != null ? wrongQuestionDto.getIsReviewed() : false)
            .masteryLevel(wrongQuestionDto.getMasteryLevel())
            .practiceSessionId(wrongQuestionDto.getPracticeSessionId())
            .errorTime(LocalDateTime.now())
            .build();
        
        WrongQuestion saved = wrongQuestionRepository.save(wrongQuestion);
        return convertToDto(saved);
    }
    
    @Override
    public List<WrongQuestionDto> addWrongQuestions(List<WrongQuestionDto> wrongQuestionDtos) {
        List<WrongQuestionDto> results = new ArrayList<>();
        for (WrongQuestionDto dto : wrongQuestionDtos) {
            results.add(addWrongQuestion(dto));
        }
        return results;
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<WrongQuestionDto> getWrongQuestionsByUserId(Long userId, Pageable pageable) {
        Page<WrongQuestion> wrongQuestions = wrongQuestionRepository.findByUserIdOrderByErrorTimeDesc(userId, pageable);
        return wrongQuestions.map(this::convertToDto);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<WrongQuestionDto> getAllWrongQuestionsByUserId(Long userId) {
        List<WrongQuestion> wrongQuestions = wrongQuestionRepository.findByUserIdOrderByErrorTimeDesc(userId);
        return wrongQuestions.stream().map(this::convertToDto).collect(Collectors.toList());
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<WrongQuestionDto> searchWrongQuestions(Long userId, String keyword, Pageable pageable) {
        Page<WrongQuestion> wrongQuestions = wrongQuestionRepository.searchByUserIdAndKeyword(userId, keyword, pageable);
        return wrongQuestions.map(this::convertToDto);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<WrongQuestionDto> getWrongQuestionsByType(Long userId, String type, Pageable pageable) {
        Page<WrongQuestion> wrongQuestions = wrongQuestionRepository.findByUserIdAndQuestionType(userId, type, pageable);
        return wrongQuestions.map(this::convertToDto);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<WrongQuestionDto> getWrongQuestionsByCategory(Long userId, Long categoryId, Pageable pageable) {
        Page<WrongQuestion> wrongQuestions = wrongQuestionRepository.findByUserIdAndQuestionCategory(userId, categoryId, pageable);
        return wrongQuestions.map(this::convertToDto);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<WrongQuestionDto> getWrongQuestionsByReviewStatus(Long userId, Boolean isReviewed, Pageable pageable) {
        Page<WrongQuestion> wrongQuestions = wrongQuestionRepository.findByUserIdAndIsReviewedOrderByErrorTimeDesc(userId, isReviewed, pageable);
        return wrongQuestions.map(this::convertToDto);
    }
    
    @Override
    public WrongQuestionDto updateWrongQuestion(Long id, WrongQuestionDto wrongQuestionDto) {
        WrongQuestion wrongQuestion = wrongQuestionRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Wrong question not found"));
        
        wrongQuestion.setUserAnswer(wrongQuestionDto.getUserAnswer());
        wrongQuestion.setCorrectAnswer(wrongQuestionDto.getCorrectAnswer());
        wrongQuestion.setErrorReason(wrongQuestionDto.getErrorReason());
        wrongQuestion.setReviewNotes(wrongQuestionDto.getReviewNotes());
        wrongQuestion.setIsReviewed(wrongQuestionDto.getIsReviewed());
        wrongQuestion.setMasteryLevel(wrongQuestionDto.getMasteryLevel());
        
        WrongQuestion saved = wrongQuestionRepository.save(wrongQuestion);
        return convertToDto(saved);
    }
    
    @Override
    public WrongQuestionDto updateReviewStatus(Long id, Boolean isReviewed, Integer masteryLevel) {
        WrongQuestion wrongQuestion = wrongQuestionRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Wrong question not found"));
        
        wrongQuestion.setIsReviewed(isReviewed);
        if (masteryLevel != null) {
            wrongQuestion.setMasteryLevel(masteryLevel);
        }
        
        WrongQuestion saved = wrongQuestionRepository.save(wrongQuestion);
        return convertToDto(saved);
    }
    
    @Override
    public WrongQuestionDto updateErrorReason(Long id, String errorReason) {
        WrongQuestion wrongQuestion = wrongQuestionRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Wrong question not found"));
        
        wrongQuestion.setErrorReason(errorReason);
        
        WrongQuestion saved = wrongQuestionRepository.save(wrongQuestion);
        return convertToDto(saved);
    }
    
    @Override
    public WrongQuestionDto updateReviewNotes(Long id, String reviewNotes) {
        WrongQuestion wrongQuestion = wrongQuestionRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("Wrong question not found"));
        
        wrongQuestion.setReviewNotes(reviewNotes);
        
        WrongQuestion saved = wrongQuestionRepository.save(wrongQuestion);
        return convertToDto(saved);
    }
    
    @Override
    public void deleteWrongQuestion(Long id) {
        wrongQuestionRepository.deleteById(id);
    }
    
    @Override
    public void deleteWrongQuestions(List<Long> ids) {
        wrongQuestionRepository.deleteAllById(ids);
    }
    
    @Override
    public void clearWrongQuestions(Long userId) {
        wrongQuestionRepository.deleteByUserId(userId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> getWrongQuestionStats(Long userId) {
        long totalCount = wrongQuestionRepository.countByUserId(userId);
        long reviewedCount = wrongQuestionRepository.countByUserIdAndIsReviewed(userId, true);
        
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalCount", totalCount);
        stats.put("reviewedCount", reviewedCount);
        stats.put("unreviewedCount", totalCount - reviewedCount);
        stats.put("masteryRate", totalCount > 0 ? Math.round((double) reviewedCount / totalCount * 100) : 0);
        
        // 获取最近错题时间
        org.springframework.data.domain.Page<WrongQuestion> recentWrongsPage = wrongQuestionRepository.findByUserIdOrderByErrorTimeDesc(userId, 
            org.springframework.data.domain.PageRequest.of(0, 1));
        List<WrongQuestion> recentWrongs = recentWrongsPage.getContent();
        if (!recentWrongs.isEmpty()) {
            stats.put("latestErrorDate", recentWrongs.get(0).getErrorTime().toLocalDate().toString());
        } else {
            stats.put("latestErrorDate", "暂无");
        }
        
        return stats;
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean isQuestionInWrongBook(Long userId, Long questionId) {
        return wrongQuestionRepository.findByUserIdAndQuestionId(userId, questionId).isPresent();
    }
    
    private WrongQuestionDto convertToDto(WrongQuestion wrongQuestion) {
        WrongQuestionDto dto = WrongQuestionDto.builder()
            .id(wrongQuestion.getId())
            .userId(wrongQuestion.getUserId())
            .questionId(wrongQuestion.getQuestionId())
            .userAnswer(wrongQuestion.getUserAnswer())
            .correctAnswer(wrongQuestion.getCorrectAnswer())
            .errorReason(wrongQuestion.getErrorReason())
            .reviewNotes(wrongQuestion.getReviewNotes())
            .isReviewed(wrongQuestion.getIsReviewed())
            .masteryLevel(wrongQuestion.getMasteryLevel())
            .practiceSessionId(wrongQuestion.getPracticeSessionId())
            .errorTime(wrongQuestion.getErrorTime())
            .createdAt(wrongQuestion.getCreatedAt())
            .updatedAt(wrongQuestion.getUpdatedAt())
            .build();
        
        // 获取题目信息
        Optional<Question> questionOpt = questionRepository.findById(wrongQuestion.getQuestionId());
        if (questionOpt.isPresent()) {
            Question question = questionOpt.get();
            dto.setQuestionContent(question.getContent());
            dto.setQuestionType(question.getType().name());
            dto.setQuestionDifficulty(question.getDifficulty().name());
            dto.setQuestionExplanation(question.getExplanation());
            dto.setQuestionImageUrl(question.getImageUrl());
            dto.setQuestionCategoryId(question.getCategoryId());
            
            // 获取分类名称
            if (question.getCategoryId() != null) {
                Optional<QuestionCategory> categoryOpt = categoryRepository.findById(question.getCategoryId());
                if (categoryOpt.isPresent()) {
                    dto.setQuestionCategoryName(categoryOpt.get().getName());
                }
            }
        }
        
        return dto;
    }
}
